package com.example.supermonkeysm.security.filter;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.supermonkeysm.security.utils.TokenUtils;
import com.example.supermonkeysm.utils.Result;
import com.example.supermonkeysm.utils.Utils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 认证权限的过滤器
 */
public class AuthenticationFilter extends BasicAuthenticationFilter {
    private final TokenUtils tokenUtils;
    private final RedisTemplate<String, Object> redisTemplate;

    public AuthenticationFilter(AuthenticationManager authenticationManager, TokenUtils tokenUtils, RedisTemplate<String, Object> redisTemplate) {
        super(authenticationManager);
        this.tokenUtils = tokenUtils;
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //获得前端头部携带的token
        String headerToken = request.getHeader("token");
        if(StringUtils.isNotBlank(headerToken)){
            //解析token
            Claims claims = tokenUtils.analysisToken(headerToken);
            if(claims != null){
                //获得用户名
                String username = claims.getSubject();
                RedisTemplate<String, Object> redisTemplate1 = Utils.setDataBase(redisTemplate, 1);
                if(Objects.equals(redisTemplate1.opsForHash().get(username, "token"), headerToken)){
                    //从redis获得用户角色
                    List<String> permissionList = Utils.castList(redisTemplate1.opsForHash().get(username, "permissions"), String.class);
                    //将权限转换成security权限
                    Collection<GrantedAuthority> authorities = new ArrayList<>();
                    for (String value : permissionList) {
                        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(value);
                        authorities.add(authority);
                    }
                    //保存到权限上下文
                    Authentication authentication = new UsernamePasswordAuthenticationToken(username, headerToken, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }else {
                    Result.customResult(response, HttpServletResponse.SC_UNAUTHORIZED, "您的账号已在其他地方登录,请重新登录!");
                    return;
                }
            }else {
                return;
            }
        }
        //放行
        chain.doFilter(request,response);
    }
}
